//
// Created by work on 24-8-22.
//

#ifndef STDDEF_H
#define STDDEF_H

#include <dist/json/json.h>
#include <iostream>

#include <os/db/db.hpp>
#include <os/db/resultset.hpp>

#define TYPE        "type"
#define DATABASE    "database"
#define RT          "rt"
#define TOKEN       "token"
#define REQ_STATE   "state"

static const std::string index_key = "index";
static const std::string user_key = "userid";
static const std::string model_key = "model";
static const std::string device_key = "device";
static const std::string yx_key = "yx";
static const std::string yc_key = "yc";
static const std::string yk_key = "yk";
static const std::string parameter_key = "parameter";

static const std::map<bool, std::string> boolToString = {
        {true,"true"},
        {false,"false"}
};
static const std::map<std::string, bool> stringToBool = {
        {"true",true},
        {"false",false}
};

#define BOOL_TO_STRING(v) boolToString.find(v)->second
#define STRING_TO_BOOL(v) stringToBool.find(v)->second

/*********************************静态单例宏，只用于类内部***************************************/
#define STATIC_SINGLETON(ClassName) \
    private: \
    ClassName() = default; \
    ~ClassName() = default; \
    ClassName(const ClassName&) = delete; \
    ClassName& operator=(const ClassName&) = delete; \
    public: \
    static ClassName& ins(){ static ClassName mgr; return mgr;}
/********************************************************************************************/


/*****************************抛出错误并定位代码位置输出到终端*************************************/
#define THROW_ERROR_WITH_INFO(msg) \
    do { \
        std::cerr << "Error in " << __FILE__ << " (" << __FUNCTION__ << " at line " << __LINE__ << "): " << msg << std::endl; \
        throw std::runtime_error(std::string("Error in ") + __FILE__ + " (" + __FUNCTION__ + " at line " + std::to_string(__LINE__) + "): " + msg); \
    } while(0)
/*********************************************************************************************/

/*****************************输出警告*************************************/
#define OUTPUT_WARNING_INFO(msg) \
    do { \
        std::cerr << "Warning in " << __FILE__ << " (" << __FUNCTION__ << " at line " << __LINE__ << "): " << msg << std::endl; \
    } while(0)
/*********************************************************************************************/


/*****************************************调试信息****************************************************/
#define OUTPUT_DEBUG_INFO(msg) \
    do { \
        std::cerr << "Debug Info: " << msg << std::endl; \
    } while(0)
/****************************************************************************************************/

/*****************************************回复请求失败****************************************************/
#define REPLY_FAILED_REQUEST(msg) \
    do { \
        res.set_header("Content-Type", "application/json"); \
        Json::Value jsonResValus = errorJson(msg); \
        res.body = jsonResValus.toStyledString().c_str(); \
        res.end(); \
    } while(0)
/****************************************************************************************************/

/*****************************************解析请求****************************************************/
#define PSRSE_JSON_REQUEST(json) \
    do { \
        Json::CharReaderBuilder builder; \
        Json::CharReader* reader = builder.newCharReader();\
        JSONCPP_STRING errs;\
        if (!reader->parse(req.body.c_str(), req.body.c_str() + req.body.length(), &json, &errs)) {\
            REPLY_FAILED_REQUEST(std::string("请求解析失败，请检查Json请求体!"+errs));\
        }\
    } while(0)
/****************************************************************************************************/

/******************************获取数据库句柄，句柄为db*******************************************/
#define GET_DB_HANDLE(CFG) \
    CConfigs::SDataBaseCfg cfg = CConfigs::ins().dateBaseCfg(CFG); \
    std::shared_ptr<iotplat::CDb> db(createDb(cfg.lib.c_str(), cfg.ip.c_str(), cfg.engine.c_str(),cfg.port)); \
    if(!db->connect(cfg.username.c_str(), cfg.password.c_str())) { \
        std::cout  << "db name:" <<   cfg.lib.c_str() << std::endl;\
        std::cout  << "ip:" <<   cfg.ip.c_str() << std::endl;\
        std::cout  << "port:" <<   cfg.port << std::endl;\
        std::cout  << "ip:" <<   cfg.ip.c_str() << std::endl;\
        std::cout  << "user:" <<   cfg.username.c_str() << std::endl; \
        std::cout  << "pwd:" <<   cfg.password.c_str() << std::endl; \
        THROW_ERROR_WITH_INFO("db connect error!");\
    }
/*********************************************************************************************/

/***************************************获取redis句柄*******************************************/
#define GET_REDIS_HANDLE    std::shared_ptr<sw::redis::Redis> redis(std::make_shared<sw::redis::Redis>("tcp://127.0.0.1:6379"))

static Json::Value successJson(std::string msg) {
    Json::Value suc;
    suc["status"] = "success";
    suc["message"] = msg.c_str();
    return suc;
}

static Json::Value errorJson(std::string msg) {
    Json::Value err;
    err["status"] = "error";
    err["message"] = msg.c_str();
    return err;
}

static Json::Value stringToJson(const std::string& str) {
    Json::Value root;
    Json::CharReaderBuilder builder;
    Json::CharReader* reader = builder.newCharReader();
    JSONCPP_STRING errs;
    if (!reader->parse(str.c_str(), str.c_str() + str.length(), &root, &errs)) {
        OUTPUT_WARNING_INFO(std::string("json parse failed!"));
    }
    return root;
}
#include <iostream>
#include <string>
#include <codecvt>
#include <locale>
#include <sstream>
#include <iomanip>


static std::string toEscapedUnicodeChar(wchar_t wc) {
    std::ostringstream oss;
    oss << '\\' << "u" << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(wc);
    return oss.str();
}

static std::string toEscapedUnicode(const std::string& utf8Str) {
    std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
    std::wstring wideStr = converter.from_bytes(utf8Str);
    std::ostringstream escaped;
    for (wchar_t wc : wideStr) {
        escaped << toEscapedUnicodeChar(wc);
    }
    return escaped.str();
}

#endif //STDDEF_H
